package com.kitten.gateway.auth;


import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.core.collection.CollUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.kitten.gateway.constant.RedisKeyConstants;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * getPermissionList() : 获取用户权限列表，要求返参是 List<String> 字符串集合，数据格式类似如 ["app:note:publish", "app:comment:publish"] ;
 * getRoleList(): 获取用户角色列表，要求返参是 List<String> 字符串集合，数据格式类似如 ["common_user", "admin"] ;
 */
@Slf4j
@Component
public class StpInterfaceImpl implements StpInterface {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private ObjectMapper objectMapper;

    /**
     * 获取权限列表
     * @param loginId  账号id
     * @param loginType 账号类型
     * @return
     */
    @SneakyThrows
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        log.info("获取权限列表 loginId:{}, loginType:{}", loginId, loginType);
        // 构造 用户 - 角色 Redis Key        user:roles:10001
        String userRoleKey = RedisKeyConstants.buildUserRoleKey(Long.valueOf(loginId.toString()));
        // 获取用户角色列表                  ["common_user", "admin"]
        String userRolesValue = redisTemplate.opsForValue().get(userRoleKey);
        if (StringUtils.isBlank(userRolesValue)) {
            return null;
        }
        // 将JSON字符串转换为List<String>
        List<String> userRoleKeys = objectMapper.readValue(userRolesValue, List.class);

        // 返回此 loginId 拥有的权限列表
        if (CollUtil.isNotEmpty(userRoleKeys)) {
            // 查询这些角色对应的权限
            // 构建 角色-权限 Redis Key 集合
            List<String> rolePermissionsKeys = userRoleKeys.stream()
                    .map(RedisKeyConstants::buildRolePermissionsKey)
                    .toList();      // role:permissions:common_user,role:permissions:admin


            // 通过 key 集合批量查询权限，提升查询性能。
            List<String> rolePermissionsValues = redisTemplate.opsForValue().multiGet(rolePermissionsKeys);         // ["[\"app:note:publish\",\"app:comment:publish\"]", "[]"]
            if (CollUtil.isNotEmpty(rolePermissionsValues)) {
                List<String> permissions = Lists.newArrayList();

                // 遍历所有角色的权限集合，统一添加到 permissions 集合中
                rolePermissionsValues.forEach(jsonValue -> {
                    try {
                        // 将 JSON 字符串转换为 List<String> 权限集合
                        List<String> rolePermissions = objectMapper.readValue(jsonValue, new TypeReference<>() {});
                        permissions.addAll(rolePermissions);
                    } catch (JsonProcessingException e) {
                        log.error("==> JSON 解析错误: ", e);
                    }
                });
                log.info("返回权限列表: {}", permissions);
                // 返回此用户所拥有的权限
                return permissions;
            }
        }
        return null;
    }


    @SneakyThrows
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        log.info("获取角色列表 loginId:{}", loginId);
        // 构造 用户 - 角色 Redis Key
        String userRolesKey = RedisKeyConstants.buildUserRoleKey(Long.valueOf(loginId.toString()));
        String useRolesValue = redisTemplate.opsForValue().get(userRolesKey);
        if (StringUtils.isBlank(useRolesValue)) {
            return null;
        }
        // 返回此 loginId 拥有的角色列表
        log.info("角色列表: {}", useRolesValue);
        // objectMapper.readValue(useRolesValue, List.class) 的作用是将 JSON 字符串转换为 List<String>
        return objectMapper.readValue(useRolesValue, new TypeReference<>(){});
    }
}
